#include "DataInStream.h"

DataInStream::DataInStream()
{
	mPos = INVALID_INDEX;
	mFileName = "";
}

DataInStream::~DataInStream()
{
	Clear();
}

void DataInStream::SetFileName(const String &fileName)
{
	mFileName = fileName;
}

String DataInStream::GetFileName()
{
	return mFileName;
}

void DataInStream::Clear()
{
	mPos = INVALID_INDEX;
	mData.Clear();
}

bool DataInStream::Load(Buffer &buffer)
{
	Clear();

	mData = buffer;
	mPos = 0;

	return true;
}

bool DataInStream::Eof() const
{
	return (mPos == INVALID_INDEX);
}

s32 DataInStream::GetPosition() const
{
	return mPos;
}

void DataInStream::SetPosition(s32 position, bool fromEnd)
{
	mPos = fromEnd ? (mData.GetSize() + position) : position;

	if (mPos < 0) mPos = INVALID_INDEX;
	if ((u32)mPos >= mData.GetSize()) mPos = INVALID_INDEX;
}


bool DataInStream::Read(c8* buffer, u32 num)
{
	if (num <= 0)
	{
		Error::Instance().SetMessage("Unable to read from the stream, must read at least 1 byte!");
		return false;
	}

	if (mPos == INVALID_INDEX)
	{
		Error::Instance().SetMessage("Unable to read from the stream, EOF has been reached!");
		return false;
	}

	if ((mPos + num) > mData.GetSize())
	{
		Error::Instance().SetMessage("Unable to read more bytes from the stream than there exists!");
		return false;
	}

	std::memcpy(buffer, &mData[mPos], num);

	mPos += num;
	if((u32)mPos >= mData.GetSize()) mPos = INVALID_INDEX;

	return true;
}


c8 DataInStream::ReadChar()
{
	c8 Char = ' ';

	Read(reinterpret_cast<c8*>(&Char), sizeof(c8));

	return Char;
}

s32 DataInStream::ReadInt()
{
	s32 Int = 0;

	Read(reinterpret_cast<c8*>(&Int), sizeof(s32));

	return Int;
}

f32 DataInStream::ReadFloat()
{
	f32 Float = 0.0f;

	Read(reinterpret_cast<c8*>(&Float), sizeof(f32));

	return Float;
}

u8 DataInStream::ReadByte()
{
	u8 Byte = 0;

	Read(reinterpret_cast<c8*>(&Byte), sizeof(u8));

	return Byte;
}

u16 DataInStream::ReadWord()
{
	u16 Word = 0;

	Read(reinterpret_cast<c8*>(&Word), sizeof(u16));

	return Word;
}

u32 DataInStream::ReadDWord()
{
	u32 DWord = 0;

	Read(reinterpret_cast<c8*>(&DWord), sizeof(u32));

	return DWord;
}
